const sass = require('sass')//sass模块处理 sass文件
const fs = require('fs')//fs模块进行文件处理
const useref = require('useref')//处理html依赖的文件问题
const loadGruntTasks = require('load-grunt-tasks')//自动加载grunt任务
const browserSync = require('browser-sync')//browserSync构建虚拟服务器实现热更新
const bs = browserSync.create()



// 1.定义变量cwd,process.cwd()方法会返回当前命令行所在的工作目录,假如这个模块在dome1项目中运行,那么工作目录就是dome1目录
const cwd = process.cwd()
//2.载入配置文件
let config ={
  //default,假设存在默认成员就不能直接替换config,需要通过Object.assign去拷贝对象
  // 配置默认的抽象路径
  
}

try {//因为require一个不存在的地址会报错所以我们用try_catch包装一下
  const loadConfig = require(`${cwd}/pages.config.js`)
  config = Object.assign({ },config,loadConfig)
} catch (error) {
  console.log(error)
}
module.exports = grunt => {
  grunt.initConfig({
    clean: ['dist/**'],//clean任务使用grunt-contrib-clean插件清理文件

    sass: {//sass任务使用sass插件编译scss文件
      options: {
        sourceMap: true,
        implementation: sass, 
      },
      main: {
        files: {
          'dist/assets/styles/main.css': 'src/assets/styles/main.scss'
        }
      }
    },

    babel: {//babel任务使用grunt-babel针对es6+语言进行编译
      options: {
        presets: ['@babel/preset-env'],
        sourceMap: true
      },
      main: {
        files: {
          'dist/assets/scripts/main.js': 'src/assets/scripts/main.js'
        }
      }
    },
    web_swig: {//web_swig使用grunt-web-swig处理html模板引擎
      options: {
        swigOptions: {
          cache: false
        },
        getData: function (tpl) {
          return config.data;
        }
      },
      main: {
        expand: true,
        cwd: 'src/',
        src: "**/*.html",
        dest: "dist/"
      },
    },

    uglify: {//uglify使用grunt-contrib-uglify压缩js文件
      production: {
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['assets/scripts/*.js'],
          dest: 'dist/',
        }]
      },
      dev: {}
    },
    cssmin: {//cssmin使用grunt-contrib-cssmin压缩css文件
      production: {
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['assets/styles/*.css'],
          dest: 'dist/',
        }]
      },
      dev: {}
    },
    htmlmin: {//htmlmin使用grunt-contrib-htmlmin压缩html文件
      production: {
        options: {
          removeComments: true,
          collapseWhitespace: true
        },
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['**/*.html'],
          dest: 'dist/'
        }]
      },
      dev: {}
    },
    image: {//对文件进行处理
      production: {
        options: {
          optipng: false,
          pngquant: true,
          zopflipng: true,
          jpegRecompress: false,
          mozjpeg: true,
          gifsicle: true,
          svgo: true
        },
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['assets/fonts/*', 'assets/images/*'],
          dest: 'dist/'
        }]
      },
      dev: {}
    },
    eslint: {//eslint对js代码做检查
      options: {
        rulePaths: ['src/assets/scripts/']
      },
      target: ['src/assets/scripts/main.js']
    },
    sasslint: {//对sass的文件检查
      main: {
        options: {
          configFile: 'config/.sass-lint.yml',
          rulePaths: ['src/assets/scripts/']
        },
        target: ['src/assets/styles/main.scss']
      }
    },
    copy: {//copy使用grunt-contrib-copy把src和public的文件拷贝到dist目录
      main: {
        files: [{
          expand: true,
          cwd: 'public/',
          src: ['**'],
          dest: 'dist/'
        },
        {
          expand: true,
          cwd: 'src',
          src: ['assets/fonts/*'],
          dest: 'dist/'
        },
        {
          expand: true,
          cwd: 'src',
          src: ['assets/images/*'],
          dest: 'dist/'
        }
      ]}
    },
    watch: {//watch使用grunt-contrib-watch监听html css  js文件的增删改查
      js: {
        files: ['src/js/*.js'],
        tasks: ['babel', 'bs-reload']
      },
      css: {
        files: ['src/scss/*.scss'],
        tasks: ['sass', 'bs-reload']
      },
      html: {
        files: ['src/**/*.html'],
        tasks: ['web_swig', 'bs-reload']
      }
    },
    
   
  })
  //创建hcb-useref使用useref解决模块依赖问题
  grunt.registerTask("hcb-useref", function () {
    const done = this.async()
    const cwd = 'dist/'
    const htmls = ['index.html', 'about.html']
    htmls.forEach((html, index) => {
      const inputHtml = fs.readFileSync(cwd + html, "utf8")
      const [code, result] = useref(inputHtml)
      for (let type in result) {
        const dests = Object.keys(result[type])
        dests.forEach(dest => {
          const src = result[type][dest].assets
          let read
          const files = src.map(file => {
            read = cwd + file
            if(file[0] === '/') {
              read = file.substr(1)
            }
            return fs.readFileSync(read)
          })
          fs.writeFile(cwd + dest, files.join(''), (err) => {
            if (err) {
                return console.error(err);
            }
          })
        })
      }
      fs.writeFile(cwd + html, code, (err) => {
        if (err) {
          return console.error(err);
        }
        if(index === htmls.length - 1) {
          done()
        }
      })
    })
  });

  // grunt.loadNpmTasks('grunt-sass')


  // 启动browserSync，开启服务，实现热更新
  grunt.registerTask("bs", function () {
    const done = this.async();
    bs.init({
      notify: false,
      port: grunt.option('port') || 2080,
      open: grunt.option('open'),
      // files: 'temp/**',
      server: {
        baseDir: ['dist', 'src', 'public'], // 按顺序查找
        routes: {
          '/node_modules': 'node_modules'
        }
      }
    }, function (err, bs) {
      done();
    });
  });
  // 包装一下broswerSync的重新加载任务
  grunt.registerTask("bs-reload", function () {
    bs.reload()
  });

  // 获取命令行参数是否含有production或者prod，判断是开发模式还是生产模式
  const mode = (grunt.option('production') || grunt.option('prod')) ? 'production': 'development'

  loadGruntTasks(grunt) // 自动加载所有的grunt插件中的任务

  // 根据命令行参数判断是否需要压缩
  grunt.registerTask('mini:production', ['image', 'uglify', 'cssmin', 'htmlmin'])
  grunt.registerTask('mini:development', [])

  grunt.registerTask('lint', ['sasslint', 'eslint'])

  grunt.registerTask('compile', ['sass', 'babel', 'web_swig'])

  grunt.registerTask('serve', ['compile', 'bs', 'watch'])

  grunt.registerTask('build', ['clean', 'compile', 'copy', 'hcb-useref', `mini:${mode}`])

  grunt.registerTask('start', ['clean', 'compile', 'copy', 'hcb-useref', 'mini:production', 'bs', 'watch'])


}
